#pragma once
#include "object.h"

namespace Pdf
{
    struct __declspec(novtable) ObjectFactory
    {
        virtual                        ~ObjectFactory() throw() {    }
        virtual void         __fastcall append(char c)          {    }
        virtual void         __fastcall append(Object::Ptr obj) {    }
        virtual Object::Ptr  __fastcall create() = 0;
    };

    template <typename ObjectType>
    class SimpleFactoryT : public ObjectFactory
    {
    public:
        virtual void         __fastcall append(char c);
        virtual Object::Ptr  __fastcall create();

    private:
        std::string                     data;
    };

    template <typename ObjectType>
    class ContainerFactoryT : public ObjectFactory
    {
    public:
        virtual void         __fastcall append(Object::Ptr obj);
        virtual Object::Ptr  __fastcall create();

    private:
        void                            push(Object::Ptr obj);
        Object::Ptr                     pop();

        std::list<Object::Ptr>          data;
    };

    class TokenFactory : public ObjectFactory
    {
    public:
        TokenFactory() throw();

    private:
        enum State 
        { 
            stFirst,
            stInteger,
            stReal,
            stKeyword, 
        };

        virtual void         __fastcall append(char c);
        virtual Object::Ptr  __fastcall create();

        State                           state;
        std::string                     data;
    };

    typedef SimpleFactoryT<Null>            NullFactory;
    typedef SimpleFactoryT<Name>            NameFactory;
    typedef SimpleFactoryT<Comment>         CommentFactory;
    typedef SimpleFactoryT<String>          StringFactory;
    typedef ContainerFactoryT<Array>        ArrayFactory;
    typedef ContainerFactoryT<Names>        NamesFactory;
    typedef ContainerFactoryT<Dictionary>   DictionaryFactory;
}

#include "object_factory.inl"